package agenda;


public class PersonalEntry extends SlottedEntry implements Occupiable {
	
	/*** Constructors */
	protected PersonalEntry(Agenda<?> agenda, int day, String subject, boolean isOccupying, int... slots) {
		// A precondition should be added here stating that the given
		// agenda is effective.
		super(agenda, day, subject);
		// This precondition should be before the call to the super-constructor.
		assert(hasValidSlot(slots));
		for (int slot: slots)
			if (isValidSlot(slot))
				occupySlot(slot);
		setOccupying(isOccupying);
		agenda.addEntry(this);
	}
	
	public PersonalEntry(int day, Agenda<? super PersonalEntry> agenda, String subject, boolean isOccupying, int... slots) {
		this(agenda, day, subject, isOccupying, slots);
	}
	
	@Override
	public boolean isOccupying() {
		return this.isOccupying;
	}

	@Override
	public void setOccupying(boolean isOccupying) {
		if (!this.isTerminated())
			this.isOccupying = isOccupying;
	}
	
	@Override
	public void turnOccupyingOn() {
		setOccupying(true);
	}
	
	@Override
	public void turnOccupyingOff() {
		setOccupying(false);
	}

	private boolean isOccupying;

	
	/*** Slots */
	public boolean occupiesSlot(int slot) {
		return isValidSlot(slot) && slots[slot - 1];
	}
	
	public void occupySlot(int slot) {
		assert isValidSlot(slot);
		slots[slot-1] = true;
	}
	
	public void freeSlot(int slot) {
		assert isValidSlot(slot);
		assert (slot != getFirstSlot()) || (getFirstSlot() != getLastSlot());
		slots[slot-1] = false;
	}

	private final boolean slots[] = new boolean[HIGHEST_SLOT-LOWEST_SLOT+1];
	
	
	/*** General purpose */
	@Override
	public PersonalEntry mergeWith(Entry other) {
		assert (other != null);
		assert (this.getDay() == other.getDay());
		assert (! this.isTerminated()) && (! other.isTerminated());
		assert (this.getAgenda() == other.getAgenda());
		assert (other instanceof PersonalEntry);
		PersonalEntry otherPersonalEntry = (PersonalEntry) other;
		this.setSubject(this.getSubject() + other.getSubject());
		this.setOccupying(this.isOccupying() || otherPersonalEntry.isOccupying());
		for (int slot=otherPersonalEntry.getFirstSlot(); slot <= otherPersonalEntry.getLastSlot(); slot++)
			if (otherPersonalEntry.occupiesSlot(slot))
				this.occupySlot(slot);
		other.terminate();
		return this;
	}
	
	/*** Auxiliaries */
	public static boolean hasValidSlot(int[] slots) {
		if (slots == null)
			return false;
		for (int slot: slots)
			if (isValidSlot(slot))
				return true;
		return false;
	}

}
